////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __WN_SURFACE_MANAGER_WINDOWS_H__
#define __WN_SURFACE_MANAGER_WINDOWS_H__

#include "WNPlatform/inc/WNSurfaceManager.h"
#include <vector>
#include "WNConcurrency/inc/WNThread.h"
#include "WNConcurrency/inc/WNCountMutex.h"
#include "WNConcurrency/inc/WNMutex.h"

namespace WNPlatform {
    class WNSurfaceWindows;
    class WNSurfaceManagerWindows : public WNSurfaceManager {
    public:
        virtual WNSurfaceManagerError Initialize();
        virtual WNSurfaceManagerError CreateSurface(WN_UINT32 _x, WN_UINT32 _y, WN_UINT32 _width, WN_UINT32 _height, WNContainers::WNResourcePointer<WNSurface>& _surface);
        virtual WNSurfaceManagerError Release();
        WNSurfaceManagerWindows();
        virtual ~WNSurfaceManagerWindows() {};
        
    private:
        explicit WNSurfaceManagerWindows(const WNSurfaceManagerWindows& _other) {}
        const WNSurfaceManagerWindows& operator=(const WNSurfaceManagerWindows& _other) { return (*this); }

        struct WindowCreationData {
            WN_UINT32 mX;
            WN_UINT32 mY;
            WN_UINT32 mWidth;
            WN_UINT32 mHeight;
            WNSurfaceManagerWindows* mManager;
            WN_BOOL   mDestroyThread;
        };

        struct WindowThread{
            WindowThread(WNContainers::WNResourcePointer<WNPlatform::WNSurfaceWindows>(_wnd));

            WNConcurrency::WNThread* mThread;
            WNContainers::WNResourcePointer<WNPlatform::WNSurfaceWindows> mWindow;
            WN_ATOM_T mExit;
        };
        
        HWND mPendingHwnd;
        static LRESULT CALLBACK WNWindowProc ( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
        static WN_BOOL WNMessagePump(WindowThread* _data);
        std::vector<WindowThread*> mMessagePumps;

        WNConcurrency::WNCountMutex mCreatedWindowLock;
        WNConcurrency::WNMutex mCallbackLock;
        WNConcurrency::WNMutex mWindowCreationLock;
    };
};

#endif//__WN_SURFACE_MANAGER_WINDOWS_H__